﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AstarTest2
{
    class Tile
    {
        public int X;
        public int Y;
        public int Type;
        public bool IsStart;
        public bool IsGoal;
        public Tile Parent;

        public int ParentCost { get; set; } // Cost of the best known path until the current position
        public int HeuristicCost { get; set; } // Heuristic cost estimate from this tile to the goal
        public int EstimatedTotalCost { get; set; } // The estimated total cost of the path, from the start to the goal THROUGH this tile

        public HashSet<Tile> Adjacencies { get; set; } // The adjacent tiles of this tile

        private Map map;

        public Tile(int x, int y, int type, Map map)
        {
            this.X = x;
            this.Y = y;
            this.Type = type;
            this.map = map;

            ParentCost = -1;
            HeuristicCost = -1;
            EstimatedTotalCost = -1;

            Adjacencies = new HashSet<Tile>();
        }

        /// <summary>
        /// Calculates the adjacent tiles.
        /// </summary>
        public void CalculateAdjacencies()
        {
            int left = X - 1;
            int right = X + 1;
            int top = Y - 1;
            int bottom = Y + 1;

            // NOTE: We only need to check the right and bottom tiles, because the left and top tiles are
            // also set in the process by allocating this tile to the right or bottom tile.
            if (right < map.Columns)
            {                        // rows, columns
                Tile rightTile = map.Tiles[Y, right];
                if (rightTile.Type == 0) // No tile present at the left
                {
                    rightTile.Adjacencies.Add(this); // Add this tile to the right tile's adjacencies
                    // THIS TILE IS THE LEFT TILE OF "rightTile"
                    this.Adjacencies.Add(rightTile); // Add the left tile to this tile's adjacencies
                }
            }

            if (bottom < map.Rows)
            {
                Tile bottomTile = map.Tiles[bottom, X];
                if (bottomTile.Type == 0) // No tile present at the bottom
                {
                    bottomTile.Adjacencies.Add(this); // THIS TILE IS THE TOP TILE OF "bottomTile"
                    this.Adjacencies.Add(bottomTile);
                }
            }
        }

        /// <summary>
        /// Gets the estimated total cost of the path, which goes from the start to the 
        /// goal VIA this tile.
        /// </summary>
        /// <param name="goal">The goal tile.</param>
        /// <returns></returns>
        public int GetTotalCost(Tile goal)
        {
            return GetParentCost() + GetHeuristicCost(goal);
        }

        /// <summary>
        /// Gets the estimated cost to get from this tile to another tile.
        /// </summary>
        /// <param name="goal">The tile to check the cost to.</param>
        /// <returns>The estimated heuristic cost to get from this tile to the specified tile.</returns>
        public int GetHeuristicCost(Tile goal)
        {
            // Manhattan method
            return Math.Abs(X - goal.X) + Math.Abs(Y - goal.Y);
        }

        /// <summary>
        /// Get the cost of the best known path until the current tile position.
        /// </summary>
        /// <param name="tile">Tile to execute recursion on, getting the cost of the parent. Recursion starts at the current location.</param>
        /// <returns>The cost of the best known path until the current tile position </returns>
        public int GetParentCost()
        {
            if (this.IsStart)
                return 0;

            return 10 + this.Parent.GetParentCost();
        }










        ///// <summary>
        ///// Gets the estimated total cost of the path, which goes from the start to the 
        ///// goal VIA this tile.
        ///// </summary>
        ///// <param name="goal">The goal tile.</param>
        ///// <returns></returns>
        //public int GetTotalCost(Tile goal)
        //{
        //    if (this.estimatedTotalCost == -1) // cost not calculated yet
        //    {
        //        this.estimatedTotalCost = GetParentCost() + GetHeuristicCost(goal);
        //    }
        //    return this.estimatedTotalCost;
        //}

        ///// <summary>
        ///// Gets the estimated cost to get from this tile to another tile.
        ///// </summary>
        ///// <param name="goal">The tile to check the cost to.</param>
        ///// <returns>The estimated heuristic cost to get from this tile to the specified tile.</returns>
        //public int GetHeuristicCost(Tile goal)
        //{
        //    if (this.heuristicCost == -1) // cost not calculated yet // GAAT MIS BIJ ACHTERUITGAAN / HERSTEL VAN PAD????
        //    {
        //        // Manhattan method
        //        this.heuristicCost = Math.Abs(X - goal.X) + Math.Abs(Y - goal.Y); 
        //    }
        //    return this.heuristicCost;
        //}

        ///// <summary>
        ///// Get the cost of the best known path until the current tile position.
        ///// </summary>
        ///// <param name="tile">Tile to execute recursion on, getting the cost of the parent. Recursion starts at the current location.</param>
        ///// <returns>The cost of the best known path until the current tile position </returns>
        //public int GetParentCost()
        //{
        //    if (this.IsStart)
        //        return 0;

        //    if (this.parentCost == -1) // cost not calculated yet
        //    {
        //        this.parentCost = 10 + this.Parent.GetParentCost();
        //    }
        //    return this.parentCost;
        //}
    }
}
